<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>网口连接模拟器 - 多设备与自定义名称</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            /* 调整 body 的顶部内边距，为固定定位的 Logo 和日期时间腾出空间 */
            /* Logo/日期时间高度70px + 顶部距离20px + 额外间距20px = 110px */
            padding: 20px 20px 20px 20px; 
            background-color: #f0f2f5;
            display: flex;
            flex-direction: column;
            align-items: center; /* 居中所有内容 */
            min-height: 100vh; /* 确保body至少占满视口高度 */
            box-sizing: border-box; /* 让padding包含在min-height内 */
        }

        /* --- LOGO及文字样式开始 --- */
        #logo-container {
            position: fixed; /* 固定在视口 */
            top: 20px;       /* 距离顶部20px，与body padding一致 */
            left: 20px;      /* 距离左侧20px，与body padding一致 */
            z-index: 1000;   /* 确保在最顶层，不被其他内容覆盖 */
            
            display: flex; /* 启用Flexbox布局 */
            align-items: center; /* 垂直居中对齐子元素 (图片和文字) */
            gap: 10px; /* 图片和文字之间的水平间距 */

            /* 您可以根据需要添加背景色或阴影，使其更突出或更好地融入 */
            /* background-color: rgba(255, 255, 255, 0.8); */ 
            /* padding: 5px 10px; */ 
            /* border-radius: 10px; */ 
            /* box-shadow: 0 2px 5px rgba(0,0,0,0.1); */ 
        }

        #logo-container img {
            width: 70px;     /* 设置logo宽度 */
            height: auto;    /* 高度自动调整，保持图片比例 */
            border-radius: 10px; /* 给logo图片添加轻微圆角，使其外观更柔和和谐 */
        }

        .logo-text {
            display: flex; /* 启用Flexbox，使两行文字垂直堆叠 */
            flex-direction: column;
            justify-content: center; /* 垂直居中两行文字 */
            /* height: 70px; /* 可以设置与logo相同的高度，确保垂直居中效果一致 */
            /* 注意：这里的 height 也可以不设置，只要 #logo-container 的 align-items: center 生效即可 */
        }

        .logo-text p {
            margin: 0; /* 移除段落的默认外边距 */
            font-family: 'KaiTi', '楷体', 'STKaiti', serif; /* 优美字体 */
            font-size: 26px; /* 调整字体大小，使其两行高度与Logo接近 */
            line-height: 1.2; /* 调整行高，使文字更紧凑 */
            color: #333; /* 文字颜色，与页面其他标题颜色相符 */
            white-space: nowrap; /* 防止文字换行 */
            text-shadow: 1px 1px 2px rgba(255,255,255,0.7); /* 添加一点点文字阴影，使其更清晰 */
        }
        /* --- LOGO及文字样式结束 --- */

        /* --- 日期时间显示样式开始 --- */
        #datetime-display {
            position: fixed; /* 固定在视口 */
            top: 20px;       /* 距离顶部20px，与logo对称 */
            right: 20px;     /* 距离右侧20px */
            z-index: 1000;   /* 确保在最顶层 */

            display: flex; /* 启用Flexbox布局 */
            flex-direction: row-reverse; /* 新增: 让按钮在日期时间左侧显示 */
            align-items: center; /* 垂直居中对齐子元素 */
            height: 70px; /* 设置与Logo相同的高度，使其垂直居中效果一致 */
            gap: 20px;   /* 新增: 按钮与日期时间之间的间距 */
            
            /* 可选：添加一些背景或阴影使其更突出 */
            /* background-color: rgba(255, 255, 255, 0.8); */
            /* padding: 5px 10px; */
            /* border-radius: 10px; */
            /* box-shadow: 0 2px 5px rgba(0,0,0,0.1); */
        }

        /* 新增：用于包裹日期和时间文本的容器，使其可以与按钮并列显示 */
        .datetime-text {
            display: flex;
            flex-direction: column;
            align-items: flex-end; /* 文本右对齐 */
        }

        #datetime-display p {
            margin: 0; /* 移除段落的默认外边距 */
            font-family: 'Segoe UI', Arial, sans-serif; /* 使用与body一致的字体，保持和谐 */
            font-size: 1.1em; /* 稍微大一点，清晰显示 */
            line-height: 1.2; /* 调整行高 */
            color: #555; /* 略深一点的灰色，与现有设计和谐 */
            text-shadow: 1px 1px 2px rgba(255,255,255,0.7); /* 柔和阴影 */
            white-space: nowrap; /* 防止换行 */
        }

        #datetime-display #current-time {
            font-size: 1.4em; /* 时间可以更大一些，更显眼 */
            font-weight: bold;
            color: #007bff; /* 使用主题蓝色，突出时间 */
        }
        /* --- 日期时间显示样式结束 --- */

        /* --- 红心动画样式开始 (从 "不要乱点哦.html" 提取并调整) --- */
        .heart-animation-container {
            position: fixed; /* 固定在视口，与Logo/日期时间保持一致 */
            width: 40px;  /* 整体尺寸，根据内部部件调整 */
            height: 38px; /* 调整高度以更好地容纳心形 */
            pointer-events: none; /* 使其不可交互，仅作为装饰 */
            z-index: 999; /* 略低于Logo和日期时间，但高于主要内容 */
            /* 移除了这里的 transform 和 animation，它们将应用于 heart-part */
        }

        .heart-part {
            position: absolute;
            background: linear-gradient(-90deg, #F50A45 0%, #d5093c 40%);
            box-shadow: 0 0 4px #d5093c; /* 调整阴影大小，适配缩小后的心形 */
            animation: beat .8s ease infinite normal; /* 动画直接应用到每个部分 */
        }

        .heart-left-circle, .heart-right-circle {
            width: 20px; /* 调整部件大小 */
            height: 20px; /* 调整部件大小 */
            border-radius: 50%;
            top: 0;
        }
        .heart-left-circle {
            left: 3.4px; /* 精确调整部件相对位置 */
        }
        .heart-right-circle {
            right: 3.4px; /* 精确调整部件相对位置 */
            z-index: -1;
        }
        .heart-bottom-square {
            width: 20px; /* 调整部件大小 */
            height: 20px; /* 调整部件大小 */
            bottom: 11.55px; /* 精确调整部件相对位置 */
            left: 10px; /* 精确调整部件相对位置 (宽度40px，方块20px，所以居中是10px) */
            transform: rotate(45deg); /* 保持底部方形旋转，形成心形尖角 */
            z-index: -1;
        }

        @keyframes beat {
            0%{
                transform: scale(1) rotate(225deg); /* 动画中包含整体旋转 */
                box-shadow:0 0 4px #d5093c;
            }
            50%{
                transform: scale(1.1) rotate(225deg); /* 跳动时放大，并保持旋转 */
                box-shadow: 0 0 5px #d5093c; /* 跳动时阴影稍大 */
            }
            100%{
                transform: scale(1) rotate(225deg);
                box-shadow: 0 0 4px #d5093c;;
            }
        }
        /* --- 红心动画样式结束 --- */


        h1 {
            color: #333;
            margin-bottom: 10px;
        }

        /* 移除了针对 body > p 的特殊 margin-bottom 样式，因为该段落已被移动 */
        /* p 标签的默认 margin-bottom: 20px; 将在其他地方生效 */

        #controls {
            background-color: #e9ecef;
            border: 1px solid #ddd;
            padding: 15px;
            margin-bottom: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 5px rgba(0,0,0,0.05);
            width: 90%;
            max-width: 1200px; /* 控制面板保持最大宽度限制 */
            display: flex;
            flex-wrap: wrap; /* 允许换行 */
            gap: 20px; /* 增加控制区组间距 */
            align-items: stretch;
            justify-content: center;
            flex-shrink: 0; /* 防止控制面板被挤压 */
        }

        .control-section {
            padding: 15px;
            border: 1px solid #ccc;
            border-radius: 6px;
            background-color: #fcfcfc;
            flex: 1; /* 弹性布局，使其占据可用空间 */
            min-width: 280px; /* 最小宽度 */
        }

        /* 新增：用于包裹“服务器/终端设备配置”和“操作指导”的容器 */
        .right-column-group {
            display: flex;
            flex-direction: column; /* 使其内部子元素垂直排列 */
            gap: 20px; /* 内部元素之间的间距 */
            flex: 1; /* 确保它在 #controls 中占据空间 */
            min-width: 280px; /* 确保其最小宽度与 .control-section 相同 */
        }

        .control-section h3 {
            margin-top: 0;
            color: #007bff;
            border-bottom: 1px solid #eee;
            padding-bottom: 8px;
            margin-bottom: 15px;
        }

        .control-group {
            display: flex;
            flex-direction: column;
            gap: 5px;
            margin-bottom: 10px;
        }

        #controls label {
            font-weight: bold;
            color: #444;
            font-size: 0.9em;
        }

        #controls input[type="number"],
        #controls input[type="text"] {
            padding: 8px;
            border: 1px solid #ccc;
            border-radius: 4px;
            font-size: 0.9em;
            width: 100%; /* 填充父容器宽度 */
            box-sizing: border-box; /* 确保 padding 和 border 不增加宽度 */
        }

        #controls .radio-group {
            display: flex;
            gap: 15px;
            margin-top: 5px;
        }
        #controls .radio-group label {
            font-weight: normal; /* 单选按钮标签不需要粗体 */
        }

        #controls button {
            padding: 10px 15px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 0.95em;
            transition: background-color 0.2s ease;
            /* margin-top: 10px; /* 按钮间距 - 由新的 action-buttons-group 统一管理 */ */
            width: auto; /* 自适应内容宽度 */
        }
        #controls button:hover {
            background-color: #0056b3;
        }
        #controls button:disabled {
            background-color: #cccccc;
            cursor: not-allowed;
        }
        .warning-text {
            color:red;
            font-size:0.8em;
            margin-top: 5px;
        }

        /* 针对操作指导框中的段落，使其与普通p标签的margin-bottom区分开 */
        .operation-guide-box p {
            margin-bottom: 0; /* 移除其自身的底部外边距，保持紧凑 */
        }


        #workspace {
            width: 90%; /* 工作区宽度仍然是body的90% */
            min-width: 1500px; /* 模拟器区域的最小宽度，如果小于屏幕，将出现水平滚动条 */
            min-height: 800px; /* 模拟器区域的最小高度，如果小于屏幕，将出现垂直滚动条 */
            
            border: 2px dashed #a0a0a0;
            position: relative;
            background-color: #ffffff;
            overflow: auto; /* 允许工作区内部滚动 */
            box-shadow: 0 4px 10px rgba(0,0,0,0.1);
            border-radius: 8px;
            margin-bottom: 20px; /* 工作区下方留白 */
        }

        /* 可拖动元素的基础样式 */
        .draggable {
            position: absolute;
            border: 1px solid #ccc;
            background-color: #f9f9f9;
            padding: 10px;
            cursor: grab;
            user-select: none;
            box-shadow: 2px 2px 5px rgba(0,0,0,0.1);
            border-radius: 6px;
            display: flex;
            flex-direction: column; /* 默认垂直布局 */
            justify-content: space-between;
            align-items: center;
            transition: box-shadow 0.15s ease-in-out;
            z-index: 10;
        }
        .draggable:active {
            cursor: grabbing;
            box-shadow: 0 0 15px rgba(0, 123, 255, 0.5);
        }
        /* 选中设备时的通用高亮 */
        .draggable.selected-element {
            border: 2px solid #007bff;
            box-shadow: 0 0 10px rgba(0, 123, 255, 0.7);
        }

        /* 交换机样式 - 调整为透明和自适应宽度 */
        .switch {
            width: auto;
            min-width: 150px; /* CSS min-width */
            min-height: 120px; /* CSS min-height */
            background-color: transparent;
            border: 1px dashed #4CAF50;
            color: #333;
            padding: 15px; /* Added to min-width/height for total size */
            text-align: center;
            border-radius: 10px;
            box-shadow: none;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: space-between;
            overflow: hidden; 
        }
        .switch-label {
            font-weight: bold;
            margin-bottom: 10px;
            font-size: 1.1em;
            color: black; /* ⬅️ 已修改为黑色 */
            text-shadow: 1px 1px 2px rgba(255,255,255,0.8);
        }

        /* 交换机内部 COM 和 VGA 图形的新容器 */
        .switch-additional-ports {
            display: flex;
            justify-content: center; /* 水平居中 */
            align-items: center;     /* 垂直居中 (如果内容有不同高度) */
            gap: 10px;               /* COM和VGA之间的间距 */
            margin-top: 10px;        /* 与上方端口区域的间距 */
            width: 100%;             /* 确保占据全部宽度以便居中 */
            flex-shrink: 0;          /* 防止被压缩 */
            box-sizing: border-box;
        }

        /* 交换机内部 COM 和 VGA 图形通用样式 */
        .com-graphic, .vga-graphic {
            font-size: 0.7em; /* 恢复字样大小 */
            font-weight: bold;
            color: #fff; 
            padding: 3px 5px;
            z-index: 15; 
            display: flex; 
            align-items: center; 
            justify-content: center; 
            flex-shrink: 0; /* 防止内容被压缩 */
            cursor: crosshair; 
            transition: background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease; 
            border: 1px solid transparent; /* 默认透明边框，以便高亮时改变 */
        }

        /* NEW: Class to hide port graphics */
        .hidden-port-graphic {
            display: none !important; /* Forces the element to be hidden */
        }

        /* 端口容器 for SWITCHES */
        .ports-container {
            display: flex;
            flex-direction: column;
            gap: 10px;
            justify-content: center;
            margin-top: 10px;
        }

        /* 端口行样式 for SWITCHES */
        .port-row {
            display: flex;
            gap: 8px;
            justify-content: center;
            flex-wrap: wrap; /* 允许端口自动换行 */
        }

        /* --- Styles for SWITCH ports (original .port class) --- */
        /* These ports have text *inside* the shape */
        .switch .port {
            width: 30px;
            height: 30px;
            background-color: #ccc;
            border-radius: 50%; /* Default to circular (electrical) */
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 0.75em;
            cursor: crosshair;
            border: 1px solid #777;
            color: #333; /* Text color for switch ports */
            font-weight: bold;
            box-sizing: border-box;
            transition: background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
            white-space: nowrap; /* Prevent text wrap */
            overflow: hidden; /* Hide overflow */
            text-overflow: ellipsis; /* Show ellipsis */
        }
        .switch .port:hover:not(.connected) {
            background-color: #e0e0e0;
            border-color: #555;
        }
        .switch .port.optical { /* 千兆光口颜色 (Amber/Orange) */
            border-radius: 0; /* Square */
            background-color: #FFC107; /* Amber/Orange */
            border-color: #FFA000;
            color: #333; /* Adapt text color for background */
        }
        
        /* NEW: 万兆光口颜色 (Pink) */
        .switch .port.ten-gig-optical {
            border-radius: 0; /* Square */
            background-color: #FF69B4; /* HotPink */
            border-color: #C71585; /* Darker pink for border */
            color: white; /* Ensure text is visible on pink */
        }


        /* 交换机内部 COM 图形样式 - 提高特异性并放在此处 */
        .switch .com-graphic {
            width: 35px; 
            height: 25px; 
            background-color: #6C757D; 
            border-color: #5a6268; 
            border-radius: 0; 
        }

        /* MODIFIED: 统一所有VGA梯形端口的大小 */
        .switch .vga-graphic, .device.display .vga-graphic {
            width: 25px; /* 统一宽度 */
            height: 25px; /* MODIFIED: 统一高度为25px，与COM端口一致 */
            background-color: #007bff; 
            border-color: #0056b3; 
            /* 倒梯形形状：下边比上边宽 */
            clip-path: polygon(10% 0%, 90% 0%, 100% 100%, 0% 100%);
            border-radius: 0; 
        }
        /* 确保显示器内部的VGA端口不显示字样 (因为HTML内容为空) */
        .device.display .vga-graphic {
            font-size: 0; /* 隐藏显示器内部VGA端口的字样 */
        }


        /* --- Styles for DEVICE ports (new structure: label + shape) --- */
        /* This is the container for a label and its shape */
        .port-group {
            display: flex;
            flex-direction: column; /* Label above shape */
            align-items: center;    /* Center label and shape horizontally */
            gap: 2px;               /* Small gap between label and shape */
            min-width: 40px; /* Ensure enough space for label if wider than shape */
        }

        .port-label {
            font-size: 0.7em; /* Smaller font for label above */
            color: #555;
            white-space: nowrap; /* Don't wrap label text */
            overflow: hidden;
            text-overflow: ellipsis;
            max-width: 60px; /* Limit label width to prevent overlap */
            text-align: center;
        }

        /* Base styles for the physical port shape for devices */
        .port-shape {
            width: 30px;
            height: 30px;
            background-color: #ccc; /* Default electrical port color */
            border-radius: 50%; /* Default to circular (electrical) */
            display: flex; /* Kept for flex properties in case content is added later */
            justify-content: center;
            align-items: center;
            cursor: crosshair;
            border: 1px solid #777;
            box-sizing: border-box;
            transition: background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
        }

        /* Device specific default port colors (when not connected) */
        .device.pc .port-shape:not(.connected),
        .device.server .port-shape:not(.connected),
        .device.router .port-shape:not(.connected) { 
            background-color: #ccffcc; /* Default green-ish for devices */
            border-color: #99bb99;
        }

        /* Optical port shape styles (square) for devices (Gigabit Optical - Amber) */
        .port-shape.optical {
            border-radius: 0; /* Square */
            background-color: #FFC107; /* Amber/Orange */
            border-color: #FFA000;
        }
        /* NEW: 万兆光口形状样式 (Square) for devices (Ten Gigabit Optical - Pink) */
        .port-shape.ten-gig-optical {
            border-radius: 0; 
            background-color: #FF69B4; 
            border-color: #C71585; 
            color: white; /* Ensure text is visible if any */
        }

        /* --- Universal CONNECTED state for ALL port types (switch .port and device .port-shape) --- */
        /* !important ensures these styles override any default or specific non-connected styles */
        .port.connected,
        .port-shape.connected,
        .com-graphic.connected, 
        .vga-graphic.connected,
        .device-com-port.connected { 
            background-color: #28a745 !important; /* 绿色 (Green) */
            border-color: #218838; /* 更深的绿色边框 */
            color: white !important; /* 确保文字在绿色背景上可见 */
            box-shadow: 0 0 8px rgba(40, 167, 69, 0.7); /* 绿色光晕 */
        }

        /* 连接涉及万兆光口时的端口颜色 (纯红色), 优先级更高 */
        /* 此处保持不变，确保万兆口仍显示红色 */
        .port.connected-via-ten-gig,
        .port-shape.connected-via-ten-gig,
        .com-graphic.connected-via-ten-gig,
        .vga-graphic.connected-via-ten-gig,
        .device-com-port.connected-via-ten-gig {
            background-color: #FF0000 !important; /* 纯红色 */
            border-color: #CC0000; /* 更深的红色边框 */
            color: white !important; /* 确保文字在纯红色背景上可见 */
            box-shadow: 0 0 10px rgba(255, 0, 0, 0.9); /* 更明显的红光 */
        }


        /* Universal HIGHLIGHT state for ALL port types */
        .port.highlight,
        .port-shape.highlight,
        .com-graphic.highlight, 
        .vga-graphic.highlight,
        .device-com-port.highlight { 
            border: 2px solid #007bff;
            box-shadow: 0 0 8px rgba(0, 123, 255, 0.7);
        }

        /* 设备（PC, Server, Router）样式 */
        .device {
            width: 100px;
            height: 90px;
            border-radius: 8px;
            font-size: 0.9em;
            color: #333;
            justify-content: space-between; /* 上下对齐名称和端口容器 */
            padding-top: 10px; /* 顶部留白 */
            padding-bottom: 10px; /* 底部留白 */
            box-sizing: border-box; /* padding不增加元素总尺寸 */
            z-index: 10; /* Ensure devices are above lines but below context menu */
        }
        /* 设备内部端口容器 - 用于横向排列多个 Port-Groups */
        .device-ports-wrapper {
            display: flex;
            flex-direction: row; /* 横向排列 Port-Groups */
            gap: 10px; /* Port-Group 之间的间距 */
            justify-content: center; /* 端口组居中 */
            align-items: flex-start; /* 顶部对齐，考虑到标签高度 */
            margin-top: 5px; /* 与设备名称的间距 */
        }

        /* MODIFIED: All PC, Server, Router to semi-transparent */
        .device.pc {
            background-color: rgba(173, 216, 230, 0.7); /* Light Blue semi-transparent */
            border-color: #87CEEB;
        }
        .device.server {
            background-color: rgba(255, 182, 193, 0.7); /* Light Pink semi-transparent */
            border-color: #FF69B4;
        }
        /* 调整 router（现在是服务器5/6）的大小，使其能容纳更多文本，并设为半透明 */
        .device.router {
            width: 130px; /* 增加宽度 */
            height: 100px; /* 增加高度 */
            background-color: rgba(218, 165, 32, 0.7); /* Goldenrod semi-transparent */
            border-color: #B8860B;
        }

        /* 新增：显示器设备样式 - 保持半透明 */
        .device.display {
            background-color: rgba(211, 211, 211, 0.7); /* Light Grey semi-transparent */
            border-color: #A9A9A9;
            width: 100px; 
            height: 90px;
        }

        /* MODIFIED: 笔记本设备样式与显示器一样大 */
        .device.laptop {
            background-color: rgba(192, 255, 192, 0.7); /* Light Green semi-transparent */
            border-color: #90EE90;
            width: 100px; /* 与显示器一样大 */
            height: 90px; /* 与显示器一样大 */
        }

        /* 新增：笔记本内部的COM端口样式（长方形） */
        .device-com-port {
            width: 40px; /* 长方形宽度 */
            height: 20px; /* 长方形高度 */
            background-color: #6C757D; /* 与交换机COM端口保持一致的颜色 */
            border-color: #5a6268;
            border-radius: 3px; /* 略微圆角 */
            display: flex;
            justify-content: center;
            align-items: center;
            /* font-size: 0.75em; /* 端口内部文字大小 */ /* 笔记本COM端口内部不再有文字，文字在port-label */
            color: #fff;
            cursor: crosshair;
            box-sizing: border-box;
            transition: background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
        }


        /* SVG 连接线样式 - 基础 */
        svg {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
            z-index: 5; /* 线条在设备之下，半透明设备可看到线 */
        }
        line {
            stroke-width: 4;
            pointer-events: all;
            cursor: pointer;
            transition: stroke-width 0.15s ease, stroke 0.15s ease;
        }

        /* 核心交换机内部连接线 (核心交换机 - 核心交换机) */
        line.internal-line {
            stroke: #0000FF; /* 纯蓝色 */
        }
        line.internal-line:hover, line.internal-line.selected-for-context {
            stroke-width: 6;
            stroke: #0000CC; /* 悬停时深蓝色 */
        }

        /* 核心交换机与外部设备连接线 (核心交换机 - PC/Server/Router) */
        line.external-line {
            stroke: #FF0000; /* 纯红色 */
        }
        line.external-line:hover, line.external-line.selected-for-context {
            stroke-width: 6;
            stroke: #CC0000; /* 悬停时深红色 */
        }

        /* 其他设备之间的连接线 (PC/Server/Router - PC/Server/Router) */
        line.neutral-line {
            stroke: #007bff; /* 默认蓝色 */
        }
        line.neutral-line:hover, line.neutral-line.selected-for-context {
            stroke-width: 6;
            stroke: #0056b3; /* 悬停时深蓝色 */
        }

        line.temp-line {
            stroke: #dc3545; /* 临时线使用红色 */
            stroke-dasharray: 5 5; /* 虚线 */
            pointer-events: none;
        }

        /* 右键菜单样式 */
        .context-menu {
            position: absolute;
            background-color: #fff;
            border: 1px solid #ddd;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            z-index: 100;
            display: none;
            flex-direction: column;
            padding: 5px 0;
            border-radius: 5px;
            min-width: 120px;
        }
        .context-menu button {
            background: none;
            border: none;
            padding: 8px 15px;
            text-align: left;
            cursor: pointer;
            font-size: 0.9em;
            color: #333;
        }
        .context-menu button:hover {
            background-color: #e9ecef;
        }

        /* 线条信息提示 (Tooltip) */
        .line-tooltip {
            position: absolute;
            background-color: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 5px 10px;
            border-radius: 4px;
            font-size: 0.85em;
            pointer-events: none;
            display: none;
            z-index: 1000;
            white-space: nowrap;
        }

        /* 框选区域样式 */
        #selectionBox {
            position: absolute;
            border: 1px dashed #007bff;
            background-color: rgba(0, 123, 255, 0.1);
            z-index: 9; /* 低于设备，避免遮挡点击 */
            display: none;
            pointer-events: none; /* 允许鼠标事件穿透到下层元素 */
        }

        /* 新按钮样式 */
        .bottom-nav-button {
            /* 基本布局和外观 */
            display: inline-flex; /* 允许内容居中对齐，并正确应用内边距 */
            align-items: center; /* 垂直居中文本 */
            justify-content: center; /* 水平居中文本 */
            padding: 8px 20px; /* 调整内边距，使按钮高度更小，宽度更适中 */
            font-size: 1.1em; /* 调整字体大小，使其更适合旁边的日期时间 */
            font-weight: bold;
            text-decoration: none; /* 移除链接的下划线 */
            color: #555; /* 文本颜色 */
            
            /* 颜色和立体感效果 */
            background-color: #e6f7ff; /* 非常淡的蓝色背景 */
            border: 1px solid #b3e0ff; /* 浅蓝色边框 */
            border-radius: 8px; /* 柔和的圆角 */
            cursor: pointer;
            outline: none; /* 移除聚焦时的轮廓线，使外观更整洁 */

            /* 3D效果：使用多重阴影 */
            /* 外阴影用于“抬升”效果，内阴影用于模拟底部“唇边” */
            box-shadow: 
                0 4px 6px rgba(0, 0, 0, 0.1), /* 主要阴影，用于抬升感 */
                inset 0 -4px 0 rgba(100, 180, 255, 0.4); /* 更深的底部边缘，带有蓝色调，增加深度 */
            
            /* 平滑过渡效果 */
            transition: all 0.15s ease-out;
        }

        .bottom-nav-button:hover {
            background-color: #d9efff; /* 悬停时背景色略深 */
            box-shadow: 
                0 6px 8px rgba(0, 0, 0, 0.2), /* 抬升效果更明显 */
                inset 0 -5px 0 rgba(100, 180, 255, 0.5); /* 底部边缘更深 */
            transform: translateY(-2px); /* 按钮轻微上移，增加悬浮感 */
        }

        .bottom-nav-button:active {
            background-color: #cce7ff; /* 点击时背景色更深 */
            box-shadow: 
                0 1px 2px rgba(0, 0, 0, 0.1), /* 阴影变平 */
                inset 0 1px 0 rgba(100, 180, 255, 0.2); /* 顶部内阴影，模拟“按下”效果 */
            transform: translateY(1px); /* 按钮下压 */
        }

        /* NEW: Styles for the action buttons group */
        .action-buttons-group {
            display: flex;
            flex-wrap: wrap; /* Allow buttons to wrap to the next line if space is limited */
            gap: 10px; /* Spacing between buttons */
            margin-top: 10px; /* Space from the input fields above */
            margin-bottom: 10px; /* Space to the warning text below */
            justify-content: flex-start; /* Align buttons to the start */
            align-items: center; /* Vertically center them if they have different heights */
        }

        /* NEW: Specific styles for the COM/VGA toggle button */
        #toggleComVgaBtn {
            padding: 6px 12px; /* Smaller padding */
            font-size: 0.85em; /* Smaller font size */
            margin-top: 0; /* Override default margin-top from #controls button */
        }
    </style>
</head>
<body>
    <!-- LOGO及文字 HTML START -->
    <!-- 将logo图片和文字放置在页面左上角，使用fixed定位使其不随滚动条移动 -->
    <div id="logo-container">
        <img src="" alt="零小汇 Logo">
        <div class="logo-text">
            <p>零小汇出品</p>
            <p>值得您放心</p>
        </div>
    </div>
    <!-- LOGO及文字 HTML END -->

    <!-- 动态红心 - Logo下方 -->
    <div class="heart-animation-container" style="top: 110px; left: 50px;">
        <div class="heart-part heart-left-circle"></div>
        <div class="heart-part heart-right-circle"></div>
        <div class="heart-part heart-bottom-square"></div>
    </div>

    <!-- 日期时间显示 HTML START -->
    <div id="datetime-display">
        <!-- 按钮移动到此处，因 flex-direction: row-reverse 会显示在左侧 -->
        <a href="https://slowroads.io" class="bottom-nav-button">想你所想</a>
        <!-- 日期时间文本包裹在新div中 -->
        <div class="datetime-text">
            <p id="current-date"></p>
            <p id="current-time"></p>
        </div>
    </div>
    <!-- 日期时间显示 HTML END -->

    <!-- 动态红心 - 日期时间下方 -->
    <div class="heart-animation-container" style="top: 110px; right: 50px;">
        <div class="heart-part heart-left-circle"></div>
        <div class="heart-part heart-right-circle"></div>
        <div class="heart-part heart-bottom-square"></div>
    </div>

    <h1>网口连接模拟器</h1>
    <!-- 原来的通用操作指导 P 标签已从此处移动到新的操作指导框中 -->

    <div id="controls">
        <div class="control-section">
            <h3>乐研设备配置</h3>
            <div class="control-group">
                <label for="currentSwitchNameInput">选中设备名称:</label>
                <input type="text" id="currentSwitchNameInput" value="" disabled>
            </div>
            <div class="control-group">
                <label for="numSwitchPorts">端口数量:</label>
                <input type="number" id="numSwitchPorts" value="" min="2" max="64" disabled>
            </div>
            <div class="control-group">
                <label for="switchStartPortName">第一个端口名称 (例如: P0, GE0):</label>
                <input type="text" id="switchStartPortName" value="" placeholder="例如：P0, GE0" disabled>
            </div>
            <div class="control-group">
                <label>端口布局:</label>
                <div class="radio-group">
                    <input type="radio" id="layoutSingle" name="portLayout" value="single-row" disabled>
                    <label for="layoutSingle">单排</label>
                    <input type="radio" id="layoutDual" name="portLayout" value="dual-row" checked disabled>
                    <label for="layoutDual">双排</label>
                </div>
            </div>
            <div class="control-group">
                <!-- MODIFIED: Label changed from "光口端口" to "千兆端口" -->
                <label for="gigabitOpticalPortsInput">千兆光口 (例如: 1,3,5 或 1-4):</label>
                <!-- MODIFIED: ID changed from opticalPortsInput to gigabitOpticalPortsInput -->
                <input type="text" id="gigabitOpticalPortsInput" value="" placeholder="例如：1,3,5 或 1-4" disabled>
            </div>
            <!-- NEW: 万兆端口配置框 -->
            <div class="control-group">
                <label for="tenGigabitOpticalPortsInput">万兆光口 (例如: 1,3,5 或 1-4):</label>
                <input type="text" id="tenGigabitOpticalPortsInput" value="" placeholder="例如：1,3,5 或 1-4" disabled>
            </div>

            <!-- NEW: 包含所有按钮的 flex 容器 -->
            <div class="action-buttons-group">
                <button id="applySwitchConfigBtn" disabled>应用配置到选中设备</button>
                <button id="addNewSwitchBtn">添加新设备</button>
                <button id="duplicateSwitchBtn" disabled>复制选中设备</button>
                <!-- START OF MODIFICATION: 更短的按钮文本 -->
                <button id="toggleComVgaBtn">隐藏 C/V 端口</button>
                <!-- END OF MODIFICATION -->
            </div>
            <p class="warning-text">警告：更改设备端口数量、名称或端口类型将断开所有与该设备的现有连接。</p>
        </div>

        <!-- 新增的包裹容器，用于垂直排列右侧的两个模块 -->
        <div class="right-column-group">
            <div class="control-section">
                <h3>服务器/终端设备配置</h3>
                <div class="control-group">
                    <label for="currentDeviceNameInput">选中设备名称:</label>
                    <input type="text" id="currentDeviceNameInput" value="" disabled>
                </div>
                <div class="control-group">
                    <label>端口类型:</label>
                    <div class="radio-group">
                        <input type="radio" id="portTypeElectrical" name="devicePortType" value="electrical" disabled>
                        <label for="portTypeElectrical">电口 (圆形)</label>
                        <input type="radio" id="portTypeOptical" name="devicePortType" value="optical" disabled>
                        <label for="portTypeOptical">光口 (方形)</label>
                    </div>
                </div>
                <button id="applyDeviceConfigBtn" disabled>应用配置到选中设备</button>
                <p class="warning-text">警告：更改端口类型将断开所有与该设备的现有连接。</p>
                <!-- 这行文字保留在服务器/终端设备配置下 -->
                <p>点击工作区中的设备以修改其名称和端口类型。</p>
            </div>

            <!-- 操作指导白框，现在位于 right-column-group 内部 -->
            <div class="control-section operation-guide-box">
                <h3>操作指导</h3>
                <p>拖动设备调整位置，点击并拖动网口进行连接；
				<br>点击**任何设备**可对其配置，右键点击连接线断开连接；
				<br>按住 <kbd>Ctrl</kbd> / <kbd>Cmd</kbd> 键点击可多选设备，在空白处点击取消多选；
				<br>随意拖动左侧设备并重命名到具体乐研型号，与右侧工装进行线路连接。
				</p>
            </div>
        </div>
    </div>

    <div id="workspace">
        <svg id="connection-svg"></svg>
        <div id="selectionBox"></div> <!-- 框选区域 -->

        <!-- 新增功能4-1-3：显示器设备 1 -->
        <div class="draggable device display" id="display1">
            <div>显示器 1</div>
            <div class="device-ports-wrapper">
                <div class="port-group">
                    <div class="port-label">VGA</div>
                    <div class="vga-graphic port" data-parent-id="display1" data-port-id="display1-vga1"></div>
                </div>
            </div>
        </div>

        <!-- 新增功能4-1-3：显示器设备 2 (复制显示器 1) -->
        <div class="draggable device display" id="display2">
            <div>显示器 2</div>
            <div class="device-ports-wrapper">
                <div class="port-group">
                    <div class="port-label">VGA</div>
                    <div class="vga-graphic port" data-parent-id="display2" data-port-id="display2-vga1"></div>
                </div>
            </div>
        </div>

        <!-- 初始设备，将由JS动态生成第一个核心交换机和重新定位其他设备 -->
        <!-- 移除 style 属性，由 JS 动态设置位置 -->
        <div class="draggable device pc" id="pc1">
            <div>服务器 1</div>
            <div class="device-ports-wrapper">
                <div class="port-group">
                    <div class="port-label">NIC</div>
                    <div class="port-shape" data-parent-id="pc1" data-port-id="pc1-nic1"></div>
                </div>
            </div>
        </div>

        <div class="draggable device pc" id="pc2">
            <div>服务器 2</div>
            <div class="device-ports-wrapper">
                <div class="port-group">
                    <div class="port-label">NIC</div>
                    <div class="port-shape" data-parent-id="pc2" data-port-id="pc2-nic1"></div>
                </div>
            </div>
        </div>

        <div class="draggable device server" id="server1">
            <div>服务器 3</div>
            <div class="device-ports-wrapper">
                <div class="port-group">
                    <div class="port-label">NIC</div>
                    <div class="port-shape" data-parent-id="server1" data-port-id="server1-nic1"></div>
                </div>
            </div>
        </div>

        <!-- 新增服务器4，与服务器3一样 -->
        <div class="draggable device server" id="server4">
            <div>服务器 4</div>
            <div class="device-ports-wrapper">
                <div class="port-group">
                    <div class="port-label">NIC</div>
                    <div class="port-shape" data-parent-id="server4" data-port-id="server4-nic1"></div>
                </div>
            </div>
        </div>

        <!-- 将router1改名为router5，并调整其大小以适应“NIC 1”等字样 -->
        <div class="draggable device router" id="router5">
            <div>服务器 5</div>
            <div class="device-ports-wrapper">
                <div class="port-group">
                    <div class="port-label">NIC 1</div>
                    <div class="port-shape" data-parent-id="router5" data-port-id="router5-nic1"></div>
                </div>
                <div class="port-group">
                    <div class="port-label">NIC 2</div>
                    <div class="port-shape" data-parent-id="router5" data-port-id="router5-nic2"></div>
                </div>
            </div>
        </div>

        <!-- 新增服务器6，复制服务器5 -->
        <div class="draggable device router" id="router6">
            <div>服务器 6</div>
            <div class="device-ports-wrapper">
                <div class="port-group">
                    <div class="port-label">NIC 1</div>
                    <div class="port-shape" data-parent-id="router6" data-port-id="router6-nic1"></div>
                </div>
                <div class="port-group">
                    <div class="port-label">NIC 2</div>
                    <div class="port-shape" data-parent-id="router6" data-port-id="router6-nic2"></div>
                </div>
            </div>
        </div>

        <!-- 新增笔记本电脑模型 -->
        <div class="draggable device laptop" id="laptop1">
            <div>笔记本 1</div>
            <div class="device-ports-wrapper">
                <div class="port-group">
                    <div class="port-label">COM</div>
                    <div class="device-com-port port" data-parent-id="laptop1" data-port-id="laptop1-com1"></div>
                </div>
            </div>
        </div>

        <div class="draggable device laptop" id="laptop2">
            <div>笔记本 2</div>
            <div class="device-ports-wrapper">
                <div class="port-group">
                    <div class="port-label">COM</div>
                    <div class="device-com-port port" data-parent-id="laptop2" data-port-id="laptop2-com1"></div>
                </div>
            </div>
        </div>

    </div>

    <!-- 右键菜单 -->
    <div id="contextMenu" class="context-menu">
        <button id="disconnectButton">断开连接</button>
    </div>

    <!-- 线条信息提示 (Tooltip) -->
    <div id="lineTooltip" class="line-tooltip"></div>

    <script>
        const workspace = document.getElementById('workspace');
        const svg = document.getElementById('connection-svg');
        const contextMenu = document.getElementById('contextMenu');
        const disconnectButton = document.getElementById('disconnectButton');
        const lineTooltip = document.getElementById('lineTooltip');
        const selectionBox = document.getElementById('selectionBox'); 

        // 日期时间显示元素
        const currentDateEl = document.getElementById('current-date');
        const currentTimeEl = document.getElementById('current-time');

        // 控制面板元素 - 交换机配置部分
        const currentSwitchNameInput = document.getElementById('currentSwitchNameInput');
        const numSwitchPortsInput = document.getElementById('numSwitchPorts');
        const switchStartPortNameInput = document.getElementById('switchStartPortName');
        const applySwitchConfigBtn = document.getElementById('applySwitchConfigBtn');
        const addNewSwitchBtn = document.getElementById('addNewSwitchBtn');
        const duplicateSwitchBtn = document.getElementById('duplicateSwitchBtn'); // Reference to the new button
        const layoutSingleRadio = document.getElementById('layoutSingle'); 
        const layoutDualRadio = document.getElementById('layoutDual');     
        const gigabitOpticalPortsInput = document.getElementById('gigabitOpticalPortsInput'); // MODIFIED: Renamed variable
        const tenGigabitOpticalPortsInput = document.getElementById('tenGigabitOpticalPortsInput'); // NEW

        // NEW: COM/VGA toggle button
        const toggleComVgaBtn = document.getElementById('toggleComVgaBtn');

        // 控制面板元素 - 服务器/终端设备配置部分
        const currentDeviceNameInput = document.getElementById('currentDeviceNameInput');
        const applyDeviceConfigBtn = document.getElementById('applyDeviceConfigBtn');
        const portTypeElectricalRadio = document.getElementById('portTypeElectrical');
        const portTypeOpticalRadio = document.getElementById('portTypeOptical');


        // --- 数据模型 ---
        // Map<elementId, { type: 'switch'|'device', displayName, numPorts?, startPortName?, layoutType?, opticalPortIndices?: number[], tenGigabitOpticalPortIndices?: number[], portType?: 'electrical'|'optical'|'vga'|'com', elementRef: DOMElement }>
        let devicesMeta = new Map();
        
        // --- 拖拽相关的全局变量 ---
        let activeDraggable = null; 
        let initialMouseX, initialMouseY; 
        let dragOffsets = new Map(); 

        // --- 选择相关的全局变量 ---
        let selectedElements = new Set(); 
        let activeConfigurableElementId = null; 

        // --- 连接相关的全局变量 ---
        let connections = []; 
        let startPortElement = null; // This will now hold either a .port (for switch) or .port-shape (for device)
        let currentLine = null; 

        // --- 框选相关的全局变量 ---
        let isSelecting = false; 
        let selectionStartX, selectionStartY; 

        // --- 布局相关的全局变量 ---
        // 交换机网格布局的起始位置和当前位置
        let currentSwitchGridX = 50; // 初始X坐标
        let currentSwitchGridY = 50; // 初始Y坐标
        // 交换机在CSS中 min-width: 150px; min-height: 120px; padding: 15px;
        // 实际宽度 = min-width + padding*2 = 150 + 30 = 180px
        // 实际高度 = min-height + padding*2 = 120 + 30 = 150px
        const SWITCH_COL_WIDTH = 180; // 交换机实际宽度 (包含padding)
        const SWITCH_ROW_HEIGHT = 150; // 交换机实际高度 (包含padding)
        const SWITCH_GRID_HORIZONTAL_GAP = 70; // 交换机之间的水平间距
        const SWITCH_GRID_VERTICAL_GAP = 50; // 交换机行之间的垂直间距
        const MAX_SWITCHES_PER_ROW = 4; // 每行最大交换机数量 (需求指定为4)
        let switchesInCurrentRowCounter = 0; // 当前行已放置的交换机数量

        // NEW: Global variable for COM/VGA port visibility state
        let comVgaHidden = false; // false means visible, true means hidden

        // --- 辅助函数 ---
        const generateId = (prefix = 'id') => `${prefix}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;

        // 获取元素在工作区内的相对位置 (offsetLeft/offsetTop 是相对于最近的定位父元素)
        const getElementOffset = (el) => {
            return {
                left: el.offsetLeft, 
                top: el.offsetTop    
            };
        };

        // 获取端口元素的中心坐标（相对于SVG工作区）
        // portEl here can be a .port (for switch) or .port-shape (for device)
        const getPortCenter = (portEl) => {
            const rect = portEl.getBoundingClientRect();
            const workspaceRect = workspace.getBoundingClientRect();
            return {
                x: (rect.left + rect.right) / 2 - workspaceRect.left + workspace.scrollLeft,
                y: (rect.top + rect.bottom) / 2 - workspaceRect.top + workspace.scrollTop
            };
        };

        // 获取设备和端口的显示名称，用于 tooltip
        function getDeviceAndPortDisplayName(portEl) {
            const parentId = portEl.dataset.parentId;
            const parentMeta = devicesMeta.get(parentId);
            let parentName = parentMeta ? parentMeta.displayName : parentId; 
            
            let portText = '';
            // 优先检查是否为COM或VGA图形 (这些是内部有文本的端口)
            if (portEl.classList.contains('com-graphic')) { // 交换机内部的COM
                portText = 'COM';
            } else if (portEl.classList.contains('vga-graphic')) { // 交换机内部的VGA 或 显示器的VGA
                portText = 'VGA'; 
            } else if (portEl.classList.contains('device-com-port')) { // 笔记本的COM
                portText = 'COM';
            } else if (portEl.classList.contains('port-shape')) { // 这是PC/Server/Router的端口形状
                const portGroup = portEl.closest('.port-group');
                if (portGroup) {
                    const portLabelEl = portGroup.querySelector('.port-label');
                    portText = portLabelEl ? portLabelEl.textContent : '';
                }
            } else if (portEl.classList.contains('port')) { // 这是交换机的普通端口
                portText = portEl.textContent;
            }

            portText = portText === 'NIC' ? '网卡' : portText; // Translate NIC for display
            return `${parentName} (${portText})`;
        }

        function generatePortName(baseName, index) {
            const match = baseName.match(/^(.*?)(\d+)$/);

            if (match) {
                const prefix = match[1]; 
                const initialNumber = parseInt(match[2], 10); 
                const numLength = match[2].length; 

                const newNumber = initialNumber + index; 
                const formattedNumber = newNumber.toString().padStart(numLength, '0');

                return `${prefix}${formattedNumber}`;
            } else {
                return `${baseName} ${index + 1}`; 
            }
        }

        // 创建端口元素（主要用于交换机动态生成端口）
        function createPortElement(parentId, startPortName, index, isGigabitOptical = false, isTenGigabitOptical = false) { // MODIFIED signature
            const portEl = document.createElement('div');
            portEl.className = 'port'; // This is for switch ports only now
            if (isGigabitOptical) { // For Gigabit Optical (Amber)
                portEl.classList.add('optical'); 
            }
            if (isTenGigabitOptical) { // For 10 Gigabit Optical (Pink)
                portEl.classList.add('ten-gig-optical');
            }
            // If a port is specified as both, ten-gig-optical will override background-color if defined later in CSS,
            // but for consistency, explicitly remove 'optical' if 'ten-gig-optical' is present due to potential overlap logic in apply config.
            if (isGigabitOptical && isTenGigabitOptical) {
                 portEl.classList.remove('optical'); 
            }

            portEl.textContent = generatePortName(startPortName, index); 
            portEl.dataset.parentId = parentId;
            portEl.dataset.portId = `${parentId}-${portEl.textContent.toLowerCase().replace(/\s/g, '')}`; // Use actual port text for unique ID
            return portEl;
        }

        // --- 拖拽和选择逻辑 ---

        // 清除所有设备的选中状态
        function clearAllSelections() {
            selectedElements.forEach(id => {
                const el = document.getElementById(id);
                if (el) {
                    el.classList.remove('selected-element');
                }
            });
            selectedElements.clear();
        }

        /**
         * 切换单个元素的选中状态 (添加或移除)。
         * 此函数不负责清除其他选中状态，只处理传入的elementId。
         * @param {string} elementId - 元素的ID。
         */
        function toggleSingleElementSelection(elementId) {
            const el = document.getElementById(elementId);
            if (!el) return;

            if (selectedElements.has(elementId)) {
                selectedElements.delete(elementId);
                el.classList.remove('selected-element');
            } else {
                selectedElements.add(elementId);
                el.classList.add('selected-element');
            }

            // 更新控制面板：如果现在只有一个被选中，就显示它的配置，否则清空
            if (selectedElements.size === 1) {
                setActiveConfigurableElement(Array.from(selectedElements)[0]);
            } else {
                setActiveConfigurableElement(null); 
            }
        }

        // 处理鼠标按下事件
        workspace.addEventListener('mousedown', (e) => {
            // 隐藏右键菜单并清除线条高亮
            contextMenu.style.display = 'none';
            document.querySelectorAll('line.selected-for-context').forEach(line => line.classList.remove('selected-for-context'));

            // 获取鼠标相对于工作区的坐标
            const workspaceRect = workspace.getBoundingClientRect();
            const mouseXInWorkspace = e.clientX - workspaceRect.left + workspace.scrollLeft;
            const mouseYInWorkspace = e.clientY - workspaceRect.top + workspace.scrollTop;

            // 1. 端口连接逻辑 (最高优先级) - now targets .port and .port-shape, and specific graphic ports
            const port = e.target.closest('.port, .port-shape, .com-graphic, .vga-graphic, .device-com-port'); 
            if (port && !port.classList.contains('connected')) {
                startPortElement = port;
                const startPos = getPortCenter(startPortElement);

                currentLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
                currentLine.setAttribute('x1', startPos.x);
                currentLine.setAttribute('y1', startPos.y);
                currentLine.setAttribute('x2', startPos.x);
                currentLine.setAttribute('y2', startPos.y);
                currentLine.setAttribute('class', 'temp-line');
                svg.appendChild(currentLine);
                e.preventDefault(); 
                return;
            }

            // 2. 设备选择和拖拽逻辑
            const clickedDraggable = e.target.closest('.draggable');
            if (clickedDraggable) {
                initialMouseX = e.clientX; 
                initialMouseY = e.clientY;

                const isAdditive = e.ctrlKey || e.metaKey; 
                const wasClickedDraggableSelected = selectedElements.has(clickedDraggable.id); 

                if (isAdditive) {
                    toggleSingleElementSelection(clickedDraggable.id);
                } else { 
                    if (!wasClickedDraggableSelected) {
                        clearAllSelections();
                        selectedElements.add(clickedDraggable.id);
                        clickedDraggable.classList.add('selected-element');
                        setActiveConfigurableElement(clickedDraggable.id); 
                    }
                }

                if (selectedElements.size > 0 && selectedElements.has(clickedDraggable.id)) {
                    activeDraggable = clickedDraggable; 
                    dragOffsets.clear(); 

                    selectedElements.forEach(id => {
                        const el = document.getElementById(id);
                        if (el) {
                            const offset = getElementOffset(el);
                            dragOffsets.set(id, { initialLeft: offset.left, initialTop: offset.top });
                            el.style.cursor = 'grabbing'; 
                            el.style.zIndex = '20'; 
                        }
                    });
                } else {
                    activeDraggable = null; 
                }
                
                e.preventDefault(); 
                return;
            }

            // 3. 框选逻辑 (点击空白处)
            if (e.target === workspace || e.target === svg || e.target === selectionBox) {
                clearAllSelections(); 
                setActiveConfigurableElement(null); 

                isSelecting = true;
                selectionStartX = mouseXInWorkspace;
                selectionStartY = mouseYInWorkspace;

                selectionBox.style.left = `${selectionStartX}px`;
                selectionBox.style.top = `${selectionStartY}px`;
                selectionBox.style.width = '0px';
                selectionBox.style.height = '0px';
                selectionBox.style.display = 'block';
                e.preventDefault(); 
                return;
            }
        });

        // 处理鼠标移动事件
        workspace.addEventListener('mousemove', (e) => {
            const workspaceRect = workspace.getBoundingClientRect();
            
            if (activeDraggable && selectedElements.size > 0) { 
                e.preventDefault();
                const dx_mouse = e.clientX - initialMouseX; 
                const dy_mouse = e.clientY - initialMouseY; 

                let groupMinX = Infinity, groupMinY = Infinity;
                let groupMaxX = -Infinity, groupMaxY = -Infinity;

                selectedElements.forEach(id => {
                    const el = document.getElementById(id);
                    if (el) {
                        const initialOffset = dragOffsets.get(id);
                        const potentialElX = initialOffset.initialLeft + dx_mouse;
                        const potentialElY = initialOffset.initialTop + dy_mouse;

                        groupMinX = Math.min(groupMinX, potentialElX);
                        groupMinY = Math.min(groupMinY, potentialElY);
                        groupMaxX = Math.max(groupMaxX, potentialElX + el.offsetWidth);
                        groupMaxY = Math.max(groupMaxY, potentialElY + el.offsetHeight);
                    }
                });

                const groupWidth = groupMaxX - groupMinX;
                const groupHeight = groupMaxY - groupMinY;

                let finalDx = dx_mouse;
                let finalDy = dy_mouse;

                if (groupMinX < 0) {
                    finalDx -= groupMinX; 
                } else if (groupMaxX > workspace.scrollWidth) {
                    finalDx -= (groupMaxX - workspace.scrollWidth); 
                }

                if (groupMinY < 0) {
                    finalDy -= groupMinY; 
                } else if (groupMaxY > workspace.scrollHeight) {
                    finalDy -= (groupMaxY - workspace.scrollHeight); 
                }
                
                selectedElements.forEach(id => {
                    const el = document.getElementById(id);
                    if (el) {
                        const initialOffset = dragOffsets.get(id);
                        el.style.left = `${initialOffset.initialLeft + finalDx}px`;
                        el.style.top = `${initialOffset.initialTop + finalDy}px`;
                        updateConnectionsForElement(id); 
                    }
                });

            } else if (currentLine) { 
                const x2 = e.clientX - workspaceRect.left + workspace.scrollLeft; 
                const y2 = e.clientY - workspaceRect.top + workspace.scrollTop;  
                currentLine.setAttribute('x2', x2);
                currentLine.setAttribute('y2', y2);

                // Check for all port types
                const targetEl = document.elementFromPoint(e.clientX, e.clientY);
                const targetPort = targetEl ? targetEl.closest('.port, .port-shape, .com-graphic, .vga-graphic, .device-com-port') : null; 

                // Clear highlight from all types of ports
                document.querySelectorAll('.port.highlight, .port-shape.highlight, .com-graphic.highlight, .vga-graphic.highlight, .device-com-port.highlight').forEach(p => p.classList.remove('highlight')); 
                
                if (targetPort && targetPort !== startPortElement && !targetPort.classList.contains('connected')) {
                    targetPort.classList.add('highlight');
                }
            } else {
                 hideLineTooltip();
            }
        });

        // 处理鼠标抬起事件
        workspace.addEventListener('mouseup', (event) => {
            if (activeDraggable) { 
                selectedElements.forEach(id => {
                    const el = document.getElementById(id);
                    if (el) {
                        el.style.cursor = 'grab'; 
                        el.style.zIndex = '10'; 
                    }
                });
                activeDraggable = null;
                dragOffsets.clear();
            } else if (currentLine) { 
                const targetEl = document.elementFromPoint(event.clientX, event.clientY);
                // Check for all port types
                const actualTargetPort = targetEl ? targetEl.closest('.port, .port-shape, .com-graphic, .vga-graphic, .device-com-port') : null; 

                // Clear highlight from all types of ports
                document.querySelectorAll('.port.highlight, .port-shape.highlight, .com-graphic.highlight, .vga-graphic.highlight, .device-com-port.highlight').forEach(p => p.classList.remove('highlight')); 

                svg.removeChild(currentLine);

                if (actualTargetPort && actualTargetPort !== startPortElement && !actualTargetPort.classList.contains('connected')) {
                    createConnection(startPortElement, actualTargetPort);
                }
                currentLine = null;
                startPortElement = null;
            } else if (isSelecting) { 
                selectionBox.style.display = 'none';
                isSelecting = false;

                const selectionRect = selectionBox.getBoundingClientRect();
                const workspaceRect = workspace.getBoundingClientRect();

                const selLeft = selectionRect.left - workspaceRect.left + workspace.scrollLeft;
                const selTop = selectionRect.top - workspaceRect.top + workspace.scrollTop;
                const selRight = selLeft + selectionRect.width;
                const selBottom = selTop + selectionRect.height;

                document.querySelectorAll('.draggable').forEach(draggableEl => {
                    const elOffset = getElementOffset(draggableEl);
                    const elLeft = elOffset.left;
                    const elTop = elOffset.top;
                    const elRight = elLeft + draggableEl.offsetWidth;
                    const elBottom = elTop + draggableEl.offsetHeight;

                    if (selLeft < elRight && selRight > elLeft &&
                        selTop < elBottom && selBottom > elTop) {
                        toggleSingleElementSelection(draggableEl.id); 
                    }
                });
            }
        });

        // --- 连接管理函数 ---
        // sourcePortEl and targetPortEl can be .port or .port-shape or .com-graphic or .vga-graphic or .device-com-port
        function createConnection(sourcePortEl, targetPortEl) {
            const sourceId = sourcePortEl.dataset.portId;
            const targetId = targetPortEl.dataset.portId;
            const sourceParentId = sourcePortEl.dataset.parentId;
            const targetParentId = targetPortEl.dataset.parentId;

            const isSourceConnected = connections.some(c => c.source.portId === sourceId || c.target.portId === sourceId);
            const isTargetConnected = connections.some(c => c.source.portId === targetId || c.target.portId === targetId);
            if (isSourceConnected || isTargetConnected) {
                console.warn('端口已被占用，无法连接。');
                return;
            }

            const connId = generateId('conn');
            const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
            line.setAttribute('id', connId);
            line.dataset.sourceId = sourceId;
            line.dataset.targetId = targetId;

            const isSourceSwitch = devicesMeta.has(sourceParentId) && devicesMeta.get(sourceParentId).type === 'switch';
            const isTargetSwitch = devicesMeta.has(targetParentId) && devicesMeta.get(targetParentId).type === 'switch';

            if (isSourceSwitch && isTargetSwitch) {
                line.classList.add('internal-line'); 
            } else if (isSourceSwitch || isTargetSwitch) {
                line.classList.add('external-line'); 
            } else {
                line.classList.add('neutral-line'); 
            }

            svg.appendChild(line);

            const connection = {
                id: connId,
                source: { elementId: sourceParentId, portId: sourceId, element: sourcePortEl, displayName: getDeviceAndPortDisplayName(sourcePortEl) },
                target: { elementId: targetParentId, portId: targetId, element: targetPortEl, displayName: getDeviceAndPortDisplayName(targetPortEl) },
                lineElement: line
            };
            connections.push(connection);

            // NEW: Check if either port is a 10 Gigabit optical port
            const isTenGigOpticalConnection = sourcePortEl.classList.contains('ten-gig-optical') || targetPortEl.classList.contains('ten-gig-optical');

            sourcePortEl.classList.add('connected');
            targetPortEl.classList.add('connected');

            // NEW: If it's a 10 Gigabit optical connection, add the specific class for pure red
            if (isTenGigOpticalConnection) {
                sourcePortEl.classList.add('connected-via-ten-gig');
                targetPortEl.classList.add('connected-via-ten-gig');
            }

            updateLinePosition(connection);

            line.addEventListener('contextmenu', (e) => handleLineContextMenu(e, connId));
            line.addEventListener('mouseenter', (e) => showLineTooltip(e, connection));
            line.addEventListener('mouseleave', hideLineTooltip);
        }

        function updateLinePosition(connection) {
            // Re-query the elements in case they moved or were re-rendered
            // Updated selector to include all types of ports
            connection.source.element = document.querySelector(`[data-port-id="${connection.source.portId}"]`);
            connection.target.element = document.querySelector(`[data-port-id="${connection.target.portId}"]`);

            if (connection.source.element && connection.target.element) {
                const sourceCenter = getPortCenter(connection.source.element);
                const targetCenter = getPortCenter(connection.target.element);

                connection.lineElement.setAttribute('x1', sourceCenter.x);
                connection.lineElement.setAttribute('y1', sourceCenter.y);
                connection.lineElement.setAttribute('x2', targetCenter.x);
                connection.lineElement.setAttribute('y2', targetCenter.y);
            } else {
                console.warn(`Port for connection ${connection.id} not found, disconnecting.`);
                disconnect(connection.id);
            }
        }

        function updateConnectionsForElement(elementId) {
            [...connections].forEach(conn => { 
                if (conn.source.elementId === elementId || conn.target.elementId === elementId) {
                    updateLinePosition(conn);
                }
            });
        }

        function disconnect(connectionId) {
            const index = connections.findIndex(c => c.id === connectionId);
            if (index > -1) {
                const conn = connections[index];

                if (conn.lineElement && conn.lineElement.parentNode === svg) {
                   svg.removeChild(conn.lineElement);
                }
                
                // Remove 'connected' class from the actual port shape/element (all types)
                if (conn.source.element) {
                    conn.source.element.classList.remove('connected');
                    conn.source.element.classList.remove('connected-via-ten-gig'); // NEW: Remove specific 10G connected class
                }
                if (conn.target.element) {
                    conn.target.element.classList.remove('connected');
                    conn.target.element.classList.remove('connected-via-ten-gig'); // NEW: Remove specific 10G connected class
                }

                connections.splice(index, 1);
            }
        }

        // 清除特定设备所有连接的通用函数
        function clearDeviceConnections(deviceId) { 
            const connectionsToDisconnect = connections.filter(c =>
                c.source.elementId === deviceId || c.target.elementId === deviceId
            ).map(c => c.id);

            connectionsToDisconnect.forEach(connId => disconnect(connId));
            console.log(`Cleared connections for ${deviceId}. Remaining connections:`, connections.length);
        }

        // --- 交换机端口配置逻辑 ---
        function configureSwitchPorts(switchId, numPorts, startPortName, switchDisplayName, layoutType, gigabitOpticalPortIndices = [], tenGigabitOpticalPortIndices = []) { // MODIFIED signature
            const switchElement = document.getElementById(switchId);
            if (!switchElement) {
                console.error(`Switch element with ID ${switchId} not found.`);
                return;
            }

            const portsContainer = switchElement.querySelector(`.ports-container`);
            const labelEl = switchElement.querySelector('.switch-label');

            if (!portsContainer || !labelEl) {
                 console.error(`Missing elements for switch ${switchId}.`);
                 return;
            }

            clearDeviceConnections(switchId); 
           
            portsContainer.innerHTML = ''; 

            labelEl.textContent = switchDisplayName;

            const createAndAppendPorts = (targetRow) => {
                for (let i = 0; i < numPorts; i++) {
                    const isCurrentPortGigabitOptical = gigabitOpticalPortIndices.includes(i); // MODIFIED variable name
                    const isCurrentPortTenGigabitOptical = tenGigabitOpticalPortIndices.includes(i); // NEW
                    // This function still creates .port elements, which are for switches.
                    const portEl = createPortElement(switchId, startPortName, i, isCurrentPortGigabitOptical, isCurrentPortTenGigabitOptical); // MODIFIED call
                    targetRow.appendChild(portEl);
                }
            };

            if (layoutType === 'single-row') {
                const singleRow = document.createElement('div');
                singleRow.className = 'port-row';
                portsContainer.appendChild(singleRow);
                createAndAppendPorts(singleRow); 
            } else { 
                const topRow = document.createElement('div');
                topRow.className = 'port-row';
                const bottomRow = document.createElement('div');
                bottomRow.className = 'port-row';
                portsContainer.appendChild(topRow);
                portsContainer.appendChild(bottomRow);

                for (let i = 0; i < numPorts; i++) {
                    const isCurrentPortGigabitOptical = gigabitOpticalPortIndices.includes(i); // MODIFIED variable name
                    const isCurrentPortTenGigabitOptical = tenGigabitOpticalPortIndices.includes(i); // NEW
                    const portEl = createPortElement(switchId, startPortName, i, isCurrentPortGigabitOptical, isCurrentPortTenGigabitOptical); // MODIFIED call
                    if (i % 2 === 0) { 
                        topRow.appendChild(portEl);
                    } else { 
                        bottomRow.appendChild(portEl);
                    }
                }
            }
            console.log(`Generated ${numPorts} ports for ${switchId} with ${layoutType} layout. Gigabit Optical ports: ${gigabitOpticalPortIndices.map(idx => idx + 1).join(',')}. Ten Gigabit Optical ports: ${tenGigabitOpticalPortIndices.map(idx => idx + 1).join(',')}.`);

            const switchMeta = devicesMeta.get(switchId);
            if (switchMeta) {
                switchMeta.numPorts = numPorts;
                switchMeta.startPortName = startPortName;
                switchMeta.displayName = switchDisplayName;
                switchMeta.layoutType = layoutType; 
                switchMeta.opticalPortIndices = gigabitOpticalPortIndices; // MODIFIED: This now stores Gigabit optical
                switchMeta.tenGigabitOpticalPortIndices = tenGigabitOpticalPortIndices; // NEW
            }
            // NEW: Apply current COM/VGA visibility setting after ports are re-rendered
            applyComVgaVisibility();
        }

        /**
         * Adds a new switch to the workspace following the grid layout.
         * @param {number} numPorts 
         * @param {string} startPortName 
         * @param {string} layoutType 
         * @param {string} customName 
         * @param {number[]} [gigabitOpticalPortIndices=[]] Optional array of 0-indexed Gigabit optical ports.
         * @param {number[]} [tenGigabitOpticalPortIndices=[]] Optional array of 0-indexed 10 Gigabit optical ports. (NEW)
         */
        function addSwitchToWorkspace(numPorts, startPortName, layoutType, customName, gigabitOpticalPortIndices = [], tenGigabitOpticalPortIndices = []) { // MODIFIED signature
            const newSwitchId = generateId('switch'); 
            const switchName = customName; 

            const switchDiv = document.createElement('div');
            switchDiv.className = 'draggable switch';
            switchDiv.id = newSwitchId;
            
            // Determine position based on grid logic
            if (switchesInCurrentRowCounter >= MAX_SWITCHES_PER_ROW) {
                // Move to next row
                currentSwitchGridX = 50; // Reset X to the start of the row
                currentSwitchGridY += (SWITCH_ROW_HEIGHT + SWITCH_GRID_VERTICAL_GAP); // Move to the next row
                switchesInCurrentRowCounter = 0; // Reset counter for the new row
            }

            switchDiv.style.left = `${currentSwitchGridX}px`;
            switchDiv.style.top = `${currentSwitchGridY}px`;

            // Prepare for the next switch in the row
            currentSwitchGridX += (SWITCH_COL_WIDTH + SWITCH_GRID_HORIZONTAL_GAP); 
            switchesInCurrentRowCounter++; 

            switchDiv.innerHTML = `
                <div class="switch-label">${switchName}</div>
                <div class="ports-container" data-parent-id="${newSwitchId}">
                    <!-- Ports will be dynamically added here by configureSwitchPorts -->
                </div>
                <!-- 新增 COM 和 VGA 图形的新容器 -->
                <div class="switch-additional-ports">
                    <!-- 为COM和VGA添加class="port"以及data-parent-id和data-port-id -->
                    <div class="com-graphic port" data-parent-id="${newSwitchId}" data-port-id="${newSwitchId}-com">COM</div>
                    <div class="vga-graphic port" data-parent-id="${newSwitchId}" data-port-id="${newSwitchId}-vga">VGA</div>
                </div>
            `;
            workspace.appendChild(switchDiv);

            devicesMeta.set(newSwitchId, {
                type: 'switch',
                displayName: switchName,
                numPorts: numPorts,
                startPortName: startPortName,
                layoutType: layoutType, 
                opticalPortIndices: [...gigabitOpticalPortIndices], // This is now Gigabit
                tenGigabitOpticalPortIndices: [...tenGigabitOpticalPortIndices], // NEW
                elementRef: switchDiv
            });

            configureSwitchPorts(newSwitchId, numPorts, startPortName, switchName, layoutType, gigabitOpticalPortIndices, tenGigabitOpticalPortIndices); // MODIFIED call
            console.log(`Added new switch: ${switchName} (ID: ${newSwitchId}) at (${switchDiv.style.left}, ${switchDiv.style.top})`);
            return newSwitchId;
        }

        // --- 服务器/终端设备配置逻辑 ---
        /**
         * Update PC/Server/Router device name and port type.
         * @param {string} deviceId - Device ID.
         * @param {string} newName - New display name.
         * @param {'electrical'|'optical'|'vga'|'com'} newPortType - New port type.
         */
        function updateDeviceConfig(deviceId, newName, newPortType) {
            const deviceElement = document.getElementById(deviceId);
            if (!deviceElement) {
                console.error(`Device element with ID ${deviceId} not found.`);
                return;
            }

            const deviceMeta = devicesMeta.get(deviceId);
            if (!deviceMeta) return;

            const oldPortType = deviceMeta.portType;
            // Only clear connections if port type actually changes AND it's not a fixed type like VGA or COM
            if (newPortType && oldPortType !== newPortType && oldPortType !== 'vga' && oldPortType !== 'com') { 
                clearDeviceConnections(deviceId); 
                console.log(`Port type changed for ${deviceId}, clearing connections.`);
            }

            const labelEl = deviceElement.querySelector('div:first-child');
            if (labelEl && newName !== undefined) {
                labelEl.textContent = newName;
                deviceMeta.displayName = newName;
            }

            if (newPortType !== undefined) {
                deviceMeta.portType = newPortType;
                // Only update visual classes for electrical/optical types. VGA/COM are handled by their specific classes.
                if (newPortType !== 'vga' && newPortType !== 'com') { 
                    const isOptical = newPortType === 'optical';
                    const portShapes = deviceElement.querySelectorAll('.port-shape'); // Target the actual shape element
                    portShapes.forEach(portShapeEl => {
                        portShapeEl.classList.remove('optical', 'ten-gig-optical'); // Clear both optical types first
                        if (isOptical) {
                            portShapeEl.classList.add('optical'); // Add Gigabit optical
                        }
                        // Note: Device configuration currently only allows 'electrical' or 'optical' (Gigabit).
                        // If device 10G optical ports were needed, this logic would expand.
                    });
                }
            }

            connections.forEach(conn => {
                if (conn.source.elementId === deviceId) {
                    conn.source.displayName = getDeviceAndPortDisplayName(conn.source.element);
                }
                if (conn.target.elementId === deviceId) {
                    conn.target.displayName = getDeviceAndPortDisplayName(conn.target.element);
                }
            });
            console.log(`Device ${deviceId} config updated: Name=${newName}, PortType=${newPortType}.`);
        }

        // --- 控制面板启用/禁用和数据填充 ---
        function setActiveConfigurableElement(elementId) {
            // 清空并禁用所有交换机配置项
            currentSwitchNameInput.value = '';
            numSwitchPortsInput.value = '';
            switchStartPortNameInput.value = '';
            gigabitOpticalPortsInput.value = ''; // MODIFIED: Renamed variable
            tenGigabitOpticalPortsInput.value = ''; // NEW
            applySwitchConfigBtn.disabled = true;
            addNewSwitchBtn.disabled = false; // Always allow adding new switch
            duplicateSwitchBtn.disabled = true; // Disable duplicate by default
            numSwitchPortsInput.disabled = true;
            switchStartPortNameInput.disabled = true;
            currentSwitchNameInput.disabled = true;
            layoutSingleRadio.disabled = true; 
            layoutDualRadio.disabled = true;   
            layoutSingleRadio.checked = false; 
            layoutDualRadio.checked = false;   
            gigabitOpticalPortsInput.disabled = true; // MODIFIED
            tenGigabitOpticalPortsInput.disabled = true; // NEW


            // 清空并禁用所有服务器/终端设备配置项
            currentDeviceNameInput.value = '';
            applyDeviceConfigBtn.disabled = true;
            currentDeviceNameInput.disabled = true;
            portTypeElectricalRadio.disabled = true;
            portTypeOpticalRadio.disabled = true;
            portTypeElectricalRadio.checked = false;
            portTypeOpticalRadio.checked = false;

            activeConfigurableElementId = elementId; 

            if (elementId) {
                const elementMeta = devicesMeta.get(elementId);
                if (elementMeta) {
                    if (elementMeta.type === 'switch') {
                        // 启用并填充交换机配置
                        currentSwitchNameInput.value = elementMeta.displayName;
                        numSwitchPortsInput.value = elementMeta.numPorts;
                        switchStartPortNameInput.value = elementMeta.startPortName;
                        applySwitchConfigBtn.disabled = false;
                        duplicateSwitchBtn.disabled = false; // Enable duplicate when a switch is selected
                        numSwitchPortsInput.disabled = false;
                        switchStartPortNameInput.disabled = false;
                        currentSwitchNameInput.disabled = false;
                        
                        layoutSingleRadio.disabled = false; 
                        layoutDualRadio.disabled = false;   
                        if (elementMeta.layoutType === 'single-row') {
                            layoutSingleRadio.checked = true;
                        } else {
                            layoutDualRadio.checked = true;
                        }

                        gigabitOpticalPortsInput.disabled = false; // MODIFIED
                        const displayGigabitOpticalPorts = elementMeta.opticalPortIndices.map(idx => idx + 1).join(','); // MODIFIED variable name
                        gigabitOpticalPortsInput.value = displayGigabitOpticalPorts;

                        tenGigabitOpticalPortsInput.disabled = false; // NEW
                        const displayTenGigabitOpticalPorts = elementMeta.tenGigabitOpticalPortIndices ? elementMeta.tenGigabitOpticalPortIndices.map(idx => idx + 1).join(',') : ''; // NEW, handle undefined
                        tenGigabitOpticalPortsInput.value = displayTenGigabitOpticalPorts; // NEW


                    } else if (elementMeta.type === 'device') {
                        // 启用并填充服务器/终端设备配置
                        currentDeviceNameInput.value = elementMeta.displayName;
                        applyDeviceConfigBtn.disabled = false;
                        currentDeviceNameInput.disabled = false;

                        // 根据端口类型启用或禁用端口类型选择
                        if (elementMeta.portType === 'vga' || elementMeta.portType === 'com') { 
                            // 对于“显示器”或“笔记本”设备，禁用端口类型选择
                            portTypeElectricalRadio.disabled = true;
                            portTypeOpticalRadio.disabled = true;
                            portTypeElectricalRadio.checked = false; 
                            portTypeOpticalRadio.checked = false;
                        } else {
                            // 对于其他设备（PC, Server, Router），启用端口类型选择
                            portTypeElectricalRadio.disabled = false;
                            portTypeOpticalRadio.disabled = false;
                            if (elementMeta.portType === 'optical') {
                                portTypeOpticalRadio.checked = true;
                            } else {
                                portTypeElectricalRadio.checked = true;
                            }
                        }
                    }
                } else {
                    console.warn(`Element meta not found for ID: ${elementId}`);
                }
            }
        }


        // --- 右键菜单逻辑 ---
        let currentContextMenuConnectionId = null;
        let currentContextMenuLineElement = null;

        function handleLineContextMenu(e, connectionId) {
            e.preventDefault();
            currentContextMenuConnectionId = connectionId;

            if (currentContextMenuLineElement) {
                currentContextMenuLineElement.classList.remove('selected-for-context');
            }

            const line = document.getElementById(connectionId);
            if (line) {
                line.classList.add('selected-for-context');
                currentContextMenuLineElement = line;
            }

            contextMenu.style.left = `${e.clientX}px`;
            contextMenu.style.top = `${e.clientY}px`;
            contextMenu.style.display = 'flex';
        }

        workspace.addEventListener('click', (e) => {
            if (!contextMenu.contains(e.target)) {
                contextMenu.style.display = 'none';
                if (currentContextMenuLineElement) {
                    currentContextMenuLineElement.classList.remove('selected-for-context');
                    currentContextMenuLineElement = null;
                }
            }
        });

        disconnectButton.addEventListener('click', () => {
            if (currentContextMenuConnectionId) {
                disconnect(currentContextMenuConnectionId);
                currentContextMenuConnectionId = null;
                contextMenu.style.display = 'none';
                if (currentContextMenuLineElement) {
                    currentContextMenuLineElement.classList.remove('selected-for-context');
                    currentContextMenuLineElement = null;
                }
            }
        });

        // --- 线条信息提示 (Tooltip) 逻辑 ---
        function showLineTooltip(e, connection) {
            lineTooltip.textContent = `${connection.source.displayName} <-> ${connection.target.displayName}`;
            lineTooltip.style.left = `${e.clientX + 15}px`;
            lineTooltip.style.top = `${e.clientY + 15}px`;
            lineTooltip.style.display = 'block';
        }

        function hideLineTooltip() {
            lineTooltip.style.display = 'none';
        }

        // --- 实时日期时间更新函数 ---
        function updateDateTime() {
            const now = new Date();
            const dateOptions = { year: 'numeric', month: '2-digit', day: '2-digit' };
            const timeOptions = { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false };

            const currentDateStr = now.toLocaleDateString('zh-CN', dateOptions); // 例如：2025/08/18
            const currentTimeStr = now.toLocaleTimeString('zh-CN', timeOptions); // 例如：14:30:05

            currentDateEl.textContent = currentDateStr;
            currentTimeEl.textContent = currentTimeStr;
        }

        // Helper function to parse port ranges from input string
        const parsePortRanges = (rawInput, numMaxPorts, fieldName) => {
            let parsedIndices = [];
            const seenIndices = new Set();
            if (rawInput) {
                const parts = rawInput.split(',').map(p => p.trim());
                for (const part of parts) {
                    if (part.includes('-')) {
                        const [start, end] = part.split('-').map(Number);
                        if (!isNaN(start) && !isNaN(end) && start >= 1 && end <= numMaxPorts && start <= end) {
                            for (let j = start; j <= end; j++) {
                                const index = j - 1;
                                if (seenIndices.has(index)) {
                                    alert(`${fieldName}中端口 ${j} 重复指定。`);
                                    return null;
                                }
                                parsedIndices.push(index);
                                seenIndices.add(index);
                            }
                        } else {
                            alert(`无效的${fieldName}端口范围: ${part}。请使用例如 "1-4" 且端口号在 1 到 ${numMaxPorts} 之间。`);
                            return null;
                        }
                    } else {
                        const portNum = Number(part);
                        if (!isNaN(portNum) && portNum >= 1 && portNum >= 1 && portNum <= numMaxPorts) {
                            const index = portNum - 1;
                            if (seenIndices.has(index)) {
                                alert(`${fieldName}中端口 ${portNum} 重复指定。`);
                                return null;
                            }
                            parsedIndices.push(index);
                            seenIndices.add(index);
                        } else {
                            alert(`无效的${fieldName}端口号: ${part}。请使用 1 到 ${numMaxPorts} 之间的数字。`);
                            return null;
                        }
                    }
                }
            }
            return parsedIndices.sort((a, b) => a - b);
        };

        // NEW FUNCTION: Toggles the visibility of COM/VGA graphic ports on switches
        function applyComVgaVisibility() {
            document.querySelectorAll('.switch .com-graphic, .switch .vga-graphic').forEach(el => {
                if (comVgaHidden) {
                    // If hiding, also disconnect any active connections on these ports
                    const portId = el.dataset.portId;
                    const connectionsToDisconnect = connections.filter(c => 
                        c.source.portId === portId || c.target.portId === portId
                    ).map(c => c.id);
                    connectionsToDisconnect.forEach(connId => disconnect(connId));

                    el.classList.add('hidden-port-graphic');
                } else {
                    el.classList.remove('hidden-port-graphic');
                }
            });
            // Update button text accordingly
            // START OF MODIFICATION: 更短的按钮文本
            toggleComVgaBtn.textContent = comVgaHidden ? '显示 C/V 端口' : '隐藏 C/V 端口';
            // END OF MODIFICATION
        }


        // --- 初始化设置和事件监听 ---
        const initializeApplication = () => {
            const DEVICE_MARGIN_TOP = 20; 
            const RIGHT_OFFSET = 50; 
            const TOP_START_OFFSET = 50; 
            const LEFT_OFFSET = 50; // New offset for left-aligned devices

            setTimeout(() => {
                const workspaceActualWidth = workspace.scrollWidth; 
                const workspaceActualHeight = workspace.scrollHeight; // Not directly used for positioning, but good to know for context

                const devicesToPositionRight = [];
                const devicesToPositionLeftDisplays = []; 
                const devicesToPositionLeftLaptops = []; 

                // Step 1: Populate devicesMeta and categorize elements for positioning
                document.querySelectorAll('.draggable.device').forEach((deviceEl) => {
                    const deviceId = deviceEl.id;
                    const deviceName = deviceEl.querySelector('div:first-child').textContent;
                    let initialPortType = 'electrical'; // Default

                    if (deviceEl.classList.contains('display')) {
                        initialPortType = 'vga'; // Fixed VGA for displays
                        devicesToPositionLeftDisplays.push(deviceEl);
                    } else if (deviceEl.classList.contains('laptop')) {
                        initialPortType = 'com'; // Fixed COM for laptops
                        devicesToPositionLeftLaptops.push(deviceEl); 
                    } else { // PC, Server, Router
                        devicesToPositionRight.push(deviceEl);
                    }
                    
                    devicesMeta.set(deviceId, {
                        type: deviceEl.classList.contains('switch') ? 'switch' : 'device',
                        displayName: deviceName,
                        portType: initialPortType, 
                        elementRef: deviceEl
                    });
                });

                // Step 2: Position devices on the RIGHT side first
                let rightSideY = TOP_START_OFFSET;
                devicesToPositionRight.forEach((deviceEl) => {
                    deviceEl.style.left = `${workspaceActualWidth - deviceEl.offsetWidth - RIGHT_OFFSET}px`;
                    deviceEl.style.top = `${rightSideY}px`;
                    rightSideY += (deviceEl.offsetHeight + DEVICE_MARGIN_TOP);
                    updateDeviceConfig(deviceEl.id, devicesMeta.get(deviceEl.id).displayName, devicesMeta.get(deviceEl.id).portType);
                });

                // Now that right-side elements are positioned, get their coordinates
                const pc1Element = document.getElementById('pc1'); // "服务器 1"
                const server1Element = document.getElementById('server1'); // "服务器 3"
                const server4Element = document.getElementById('server4'); // "服务器 4"

                const gapBetweenDevices = 50; 

                // Step 3: Position Display devices to the left of PC1 ("服务器 1")
                if (pc1Element) {
                    // Sort display devices by their current HTML order to maintain relative vertical position
                    // This ensures display1 is above display2
                    devicesToPositionLeftDisplays.sort((a, b) => {
                        const idA = a.id.replace('display', '');
                        const idB = b.id.replace('display', '');
                        return parseInt(idA) - parseInt(idB);
                    });

                    let currentDisplayY = pc1Element.offsetTop; 
                    devicesToPositionLeftDisplays.forEach((displayEl) => {
                        const displayWidth = displayEl.offsetWidth;
                        displayEl.style.left = `${pc1Element.offsetLeft - displayWidth - gapBetweenDevices}px`;
                        displayEl.style.top = `${currentDisplayY}px`;
                        currentDisplayY += (displayEl.offsetHeight + DEVICE_MARGIN_TOP); // Stack vertically
                        updateDeviceConfig(displayEl.id, devicesMeta.get(displayEl.id).displayName, devicesMeta.get(displayEl.id).portType);
                    });
                } else {
                    console.error("无法找到 pc1 元素进行显示器定位。"); 
                }

                // Step 4: Position Laptop devices to the left of Server1 ("服务器 3") and Server4 ("服务器 4")
                if (server1Element && server4Element) {
                    const laptop1El = document.getElementById('laptop1');
                    const laptop2El = document.getElementById('laptop2');

                    if (laptop1El) {
                        const laptopWidth = laptop1El.offsetWidth;
                        laptop1El.style.left = `${server1Element.offsetLeft - laptopWidth - gapBetweenDevices}px`;
                        laptop1El.style.top = `${server1Element.offsetTop}px`;
                        updateDeviceConfig(laptop1El.id, devicesMeta.get(laptop1El.id).displayName, devicesMeta.get(laptop1El.id).portType);
                    }
                    if (laptop2El) {
                        const laptopWidth = laptop2El.offsetWidth; // Assuming same width
                        laptop2El.style.left = `${server4Element.offsetLeft - laptopWidth - gapBetweenDevices}px`;
                        laptop2El.style.top = `${server4Element.offsetTop}px`;
                        updateDeviceConfig(laptop2El.id, devicesMeta.get(laptop2El.id).displayName, devicesMeta.get(laptop2El.id).portType);
                    }
                } else {
                    console.error("无法找到 server1/server4 元素进行笔记本定位。"); 
                }

                // Step 5: Add the first switch and select it
                let nextSwitchNumber = 1;
                devicesMeta.forEach((meta) => {
                    if (meta.type === 'switch') {
                        const match = meta.displayName.match(/设备 (\d+)$/);
                        if (match) {
                            const num = parseInt(match[1], 10);
                            if (!isNaN(num) && num >= nextSwitchNumber) {
                                nextSwitchNumber = num + 1;
                            }
                        }
                    }
                });

                // Add the first switch, it will follow the grid layout
                const newSwitchId = addSwitchToWorkspace(
                    8,          // numPorts
                    'GE0',      // startPortName
                    'dual-row', // layoutType
                    `设备 ${nextSwitchNumber}`,
                    [],         // initial Gigabit optical ports (empty by default for new switch)
                    []          // initial Ten Gigabit optical ports (NEW)
                );
                // Default select the newly added switch
                clearAllSelections(); 
                toggleSingleElementSelection(newSwitchId); 
                console.log("New switch added and selected:", newSwitchId); 
            }, 0); 

            // --- Event Listeners ---

            // Switch configuration button
            applySwitchConfigBtn.addEventListener('click', () => {
                console.log("Apply Switch Config button clicked.");
                if (!activeConfigurableElementId || !selectedElements.has(activeConfigurableElementId)) {
                    alert('请先点击选择一个设备。');
                    return;
                }
                const currentMeta = devicesMeta.get(activeConfigurableElementId);
                if (currentMeta.type !== 'switch') {
                    alert('当前选择的不是交换机类型的设备，无法应用交换机配置。');
                    return;
                }

                const numPorts = parseInt(numSwitchPortsInput.value);
                const startPortName = switchStartPortNameInput.value.trim();
                const switchName = currentSwitchNameInput.value.trim();
                const currentLayoutType = layoutSingleRadio.checked ? 'single-row' : 'dual-row';
                const gigabitOpticalPortsRaw = gigabitOpticalPortsInput.value.trim(); // MODIFIED variable name
                const tenGigabitOpticalPortsRaw = tenGigabitOpticalPortsInput.value.trim(); // NEW

                if (isNaN(numPorts) || numPorts < 2 || numPorts > 64) {
                    alert('请输入有效的端口数量 (2-64之间的整数)。');
                    return;
                }
                if (!startPortName) {
                    alert('请输入第一个端口的名称。');
                    return;
                }
                if (!switchName) {
                    alert('请输入设备的名称。');
                    return;
                }

                let newGigabitOpticalPortIndices = parsePortRanges(gigabitOpticalPortsRaw, numPorts, '千兆端口'); // MODIFIED: Renamed variable
                if (newGigabitOpticalPortIndices === null) return; // Error occurred during parsing

                let newTenGigabitOpticalPortIndices = parsePortRanges(tenGigabitOpticalPortsRaw, numPorts, '万兆端口'); // NEW
                if (newTenGigabitOpticalPortIndices === null) return; // Error occurred during parsing

                // NEW Validation: Check for overlap between Gigabit and 10 Gigabit ports
                const gigabitSet = new Set(newGigabitOpticalPortIndices);
                const tenGigabitSet = new Set(newTenGigabitOpticalPortIndices);

                for (const tenGigIndex of tenGigabitSet) {
                    if (gigabitSet.has(tenGigIndex)) {
                        alert(`端口 ${tenGigIndex + 1} 不能同时被指定为千兆端口和万兆端口。请检查您的配置。`);
                        return;
                    }
                }

                configureSwitchPorts(
                    activeConfigurableElementId,
                    numPorts,
                    startPortName,
                    switchName,
                    currentLayoutType,
                    newGigabitOpticalPortIndices,    // MODIFIED: This is now Gigabit
                    newTenGigabitOpticalPortIndices  // NEW
                );
                setActiveConfigurableElement(activeConfigurableElementId);
            });

            // Add new switch button
            addNewSwitchBtn.addEventListener('click', () => {
                console.log("Add new switch button clicked!");
                let nextSwitchNumberForNew = 1; 
                 devicesMeta.forEach((meta) => {
                    if (meta.type === 'switch') {
                        const match = meta.displayName.match(/设备 (\d+)$/);
                        if (match) {
                            const num = parseInt(match[1], 10);
                            if (!isNaN(num) && num >= nextSwitchNumberForNew) {
                                nextSwitchNumberForNew = num + 1;
                            }
                        }
                    }
                });

                // 调用addSwitchToWorkspace，不传入坐标，让它使用网格布局
                const newSwitchId = addSwitchToWorkspace(
                    8,          // numPorts
                    'GE0',      // startPortName
                    'dual-row', // layoutType
                    `设备 ${nextSwitchNumberForNew}`,
                    [],         // Gigabit optical ports (default empty)
                    []          // Ten Gigabit optical ports (default empty) - NEW
                );
                clearAllSelections(); // 清除之前的选中
                toggleSingleElementSelection(newSwitchId); // 选中新添加的交换机
                console.log("New switch added and selected:", newSwitchId); 
            });

            // Duplicate Switch Button
            duplicateSwitchBtn.addEventListener('click', () => {
                console.log("Duplicate Switch button clicked!");
                if (!activeConfigurableElementId) {
                    alert('请先点击选择一个要复制的交换机。');
                    return;
                }
                const sourceMeta = devicesMeta.get(activeConfigurableElementId);
                if (!sourceMeta || sourceMeta.type !== 'switch') {
                    alert('当前选中的不是交换机类型，无法复制。');
                    return;
                }

                const newDisplayName = `${sourceMeta.displayName} (复制)`; 
                
                // Calling addSwitchToWorkspace, let it use grid layout
                const newSwitchId = addSwitchToWorkspace(
                    sourceMeta.numPorts,
                    sourceMeta.startPortName,
                    sourceMeta.layoutType,
                    newDisplayName,
                    sourceMeta.opticalPortIndices, // This is now Gigabit optical
                    sourceMeta.tenGigabitOpticalPortIndices // NEW
                );

                clearAllSelections();
                toggleSingleElementSelection(newSwitchId);
                console.log(`Duplicated switch: ${sourceMeta.displayName} to ${newDisplayName} (ID: ${newSwitchId})`);
            });


            // Switch layout radio buttons
            layoutSingleRadio.addEventListener('change', () => {
                if (activeConfigurableElementId) {
                    const meta = devicesMeta.get(activeConfigurableElementId);
                    if (meta && meta.type === 'switch') {
                        configureSwitchPorts(
                            activeConfigurableElementId,
                            meta.numPorts,
                            meta.startPortName,
                            meta.displayName,
                            'single-row',
                            meta.opticalPortIndices, // Gigabit optical
                            meta.tenGigabitOpticalPortIndices // NEW
                        );
                        meta.layoutType = 'single-row';
                    }
                }
            });

            layoutDualRadio.addEventListener('change', () => {
                if (activeConfigurableElementId) {
                    const meta = devicesMeta.get(activeConfigurableElementId);
                    if (meta && meta.type === 'switch') {
                        configureSwitchPorts(
                            activeConfigurableElementId,
                            meta.numPorts,
                            meta.startPortName,
                            meta.displayName,
                            'dual-row',
                            meta.opticalPortIndices, // Gigabit optical
                            meta.tenGigabitOpticalPortIndices // NEW
                        );
                        meta.layoutType = 'dual-row';
                    }
                }
            });

            // Server/Terminal device config button (name and port type)
            applyDeviceConfigBtn.addEventListener('click', () => {
                console.log("Apply Device Config button clicked.");
                if (!activeConfigurableElementId || !selectedElements.has(activeConfigurableElementId)) {
                    alert('请先点击选择一个服务器/终端设备。');
                    return;
                }
                const currentMeta = devicesMeta.get(activeConfigurableElementId);
                if (currentMeta.type !== 'device') {
                    alert('当前选择的不是服务器/终端设备，无法应用名称和端口配置。');
                    return;
                }
                const newName = currentDeviceNameInput.value.trim();
                if (!newName) {
                    alert('请输入设备名称。');
                    return;
                }
                // Only allow changing port type if it's not a fixed VGA or COM type
                const newPortType = (currentMeta.portType === 'vga' || currentMeta.portType === 'com') ? currentMeta.portType : (portTypeOpticalRadio.checked ? 'optical' : 'electrical'); 

                updateDeviceConfig(activeConfigurableElementId, newName, newPortType);
                setActiveConfigurableElement(activeConfigurableElementId); 
            });

            // NEW: Event listener for the COM/VGA toggle button
            toggleComVgaBtn.addEventListener('click', () => {
                comVgaHidden = !comVgaHidden; // Toggle the state
                applyComVgaVisibility(); // Apply the new visibility
            });


            // Ensure line positions are correct after page load (after elements have rendered and positioned)
            window.addEventListener('load', () => {
                connections.forEach(conn => updateLinePosition(conn));
            });

            // Initial call to display date and time
            updateDateTime();
            // Update date and time every second
            setInterval(updateDateTime, 1000);

            // NEW: Initial call to apply COM/VGA visibility (default should be visible)
            applyComVgaVisibility();
        };

        initializeApplication();

    </script>
</body>
</html>